package com.examples.chartdirector;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

import com.examples.chartdirector.AreaCharts.AreaLineChart;
import com.examples.chartdirector.AreaCharts.DualXAxis;
import com.examples.chartdirector.AreaCharts.SimpleAreaChart;
import com.examples.chartdirector.BarCharts.BarLabels;
import com.examples.chartdirector.BarCharts.HistogramWithBellCurve;
import com.examples.chartdirector.BarCharts.MultiColorBar;
import com.examples.chartdirector.BarCharts.SimpleBarChart1;
import com.examples.chartdirector.BarCharts.SimpleBarChart2;
import com.examples.chartdirector.FinancialCharts.FinanceChart1;
import com.examples.chartdirector.FinancialCharts.FinanceChart2;
import com.examples.chartdirector.FinancialCharts.FinanceChartCustomSymbols;
import com.examples.chartdirector.FinancialCharts.FinanceDemoChart;
import com.examples.chartdirector.FinancialCharts.SimpleCandlestickChart;
import com.examples.chartdirector.FinancialCharts.SimpleHLOCChart;
import com.examples.chartdirector.FloatingOrWaterfallCharts.BoxWhiskerChart1;
import com.examples.chartdirector.FloatingOrWaterfallCharts.BoxWhiskerChart2;
import com.examples.chartdirector.LineCharts.CompactLineChart;
import com.examples.chartdirector.LineCharts.GeneralCurveFitting;
import com.examples.chartdirector.LineCharts.MultiLineChart;
import com.examples.chartdirector.LineCharts.SimpleLineChart;
import com.examples.chartdirector.LineCharts.TrendLineChart;
import com.examples.chartdirector.PieCharts.PieChart3D;
import com.examples.chartdirector.PieCharts.SimplePieChart;
import com.examples.chartdirector.ui.ApplicationFrame;
import com.examples.chartdirector.ui.UIUtils;

public class ChartDirectorDemo extends ApplicationFrame
		implements ActionListener, TreeSelectionListener, ChangeListener {

	/** Default size for the content panel in the demo applications. */
    public static final Dimension DEFAULT_CONTENT_SIZE 
            = new Dimension(650, 790);

	private static final long serialVersionUID = 1L;
    public static final String EXIT_COMMAND = "EXIT";
    private JPanel displayPanel;
    private JPanel chartContainer;
    private JPanel descriptionContainer;
    private JTextPane descriptionPane;
//    private JEditorPane editorPane;
    private TreePath defaultChartPath;
    JTabbedPane tabs;
    private JMenuItem exportToPDFMenuItem;
    private JMenuItem exportToSVGMenuItem;

    public ChartDirectorDemo(final String title) {
        super(title);
        this.setContentPane(this.createContent());
    }

    private JComponent createContent() {
        final JPanel content = new JPanel(new BorderLayout());
        (this.tabs = new JTabbedPane()).addChangeListener(this);
        final JPanel content2 = new JPanel(new BorderLayout());
        content2.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        final JSplitPane splitter = new JSplitPane(1);
        final JTree tree = new JTree(this.createTreeModel());
        tree.addTreeSelectionListener(this);
        final JScrollPane treePane = new JScrollPane(tree);
        treePane.setPreferredSize(new Dimension(300, 100));
        splitter.setLeftComponent(treePane);
        splitter.setRightComponent(this.createChartDisplayPanel());
        content2.add(splitter);
        splitter.setDividerLocation(0.2);
        this.tabs.add("Demos", content2);
//        final MemoryUsageDemo this$0;
//        final MemoryUsageDemo memUse = this$0 = new MemoryUsageDemo(300000);
//        Objects.requireNonNull(this$0);
//        this$0.new DataGenerator(1000).start();
//        this.tabs.add("Memory Usage", memUse);
        this.tabs.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        content.add(this.tabs);
        tree.setSelectionPath(this.defaultChartPath);
        return content;
    }
    
    @Override
    public void actionPerformed(final ActionEvent event) {
        final String command = event.getActionCommand();
        if (command.equals("EXPORT_TO_PDF")) {
            this.exportToPDF();
        }
        else if (command.equals("EXPORT_TO_SVG")) {
            this.exportToSVG();
        }
        else if (command.equals("COPY")) {
            this.copyToClipboard();
        }
        else if (command.equals("EXIT")) {
            System.exit(0);
        }
    }

    private void exportToPDF() {}
    private void exportToSVG() {}
    private void copyToClipboard() {}

	@Override
	public void stateChanged(final ChangeEvent e) {
		if (e.getSource() instanceof JTabbedPane) {
			final JTabbedPane p = (JTabbedPane) e.getSource();
			if (this.exportToSVGMenuItem != null) {
				this.exportToSVGMenuItem.setEnabled(p.getSelectedIndex() == 0);
			}
			if (this.exportToPDFMenuItem != null) {
				this.exportToPDFMenuItem.setEnabled(p.getSelectedIndex() == 0);
			}
		}
	}

	private JPanel createChartDisplayPanel() {
        (this.displayPanel = new JPanel(new BorderLayout())).setPreferredSize(DEFAULT_CONTENT_SIZE);
        (this.chartContainer = new JPanel(new BorderLayout())).setPreferredSize(DEFAULT_CONTENT_SIZE);
        this.chartContainer.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4), BorderFactory.createLineBorder(Color.BLACK)));
        this.chartContainer.add(this.createNoDemoSelectedPanel());
        (this.descriptionContainer = new JPanel(new BorderLayout())).setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        this.descriptionContainer.setPreferredSize(new Dimension(600, 140));
        (this.descriptionPane = new JTextPane()).setEditable(false);
        final JScrollPane scroller = new JScrollPane(this.descriptionPane, 20, 31);
        this.descriptionContainer.add(scroller);
        this.displayDescription("select.html");
        final JSplitPane splitter = new JSplitPane(0);
        splitter.setTopComponent(this.chartContainer);
        splitter.setBottomComponent(this.descriptionContainer);
        this.displayPanel.add(splitter);
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                splitter.setDividerLocation(0.6);
            }
        });
        return this.displayPanel;
    }

    private MutableTreeNode createNode(final Class<?> demoClass, final String file) {
        return new DefaultMutableTreeNode(new DemoDescription(demoClass, file));
    }
    
    private TreeModel createTreeModel() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("ChartDirector");
        root.add(this.createPieChartsNode(root));
        root.add(this.createBarChartsNode(root));
        root.add(this.createLineChartsNode(root));
        root.add(this.createAreaChartsNode());
        root.add(this.createFloatingBoxOrWaterfallChartsNode());
        root.add(this.createFinancialChartsNode(root));
        root.add(this.createCombinedAxisChartsNode());
        root.add(this.createGanttChartsNode());
        root.add(this.createMeterChartsNode());
        root.add(this.createMultipleAxisChartsNode());
        root.add(this.createOverlaidChartsNode());
        root.add(this.createSankeyChartsNode());
        root.add(this.createTimeSeriesChartsNode());
        root.add(this.createXYChartsNode());
        root.add(this.createMiscellaneousChartsNode());
        return new DefaultTreeModel(root);
    }

    private MutableTreeNode createPieChartsNode(final DefaultMutableTreeNode r) {
    	final DefaultMutableTreeNode root = new DefaultMutableTreeNode("*** Pie Charts ***");
        final MutableTreeNode defaultNode = this.createNode(SimplePieChart.class, "SimplePieChart.java");
        this.defaultChartPath = new TreePath(new Object[] { r, root, defaultNode });
        root.add(defaultNode);
        root.add(this.createNode(PieChart3D.class, "PieChart3D.java"));
        return root;
    }
    
    private MutableTreeNode createOverlaidChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Overlaid Charts");
//        root.add(this.createNode(OverlaidChartDemo1.class, "OverlaidChartDemo1.java"));
//        root.add(this.createNode(OverlaidBarChartDemo1.class, "OverlaidBarChartDemo1.java"));
//        root.add(this.createNode(OverlaidBarChartDemo2.class, "OverlaidBarChartDemo2.java"));
//        root.add(this.createNode(OverlaidXYPlotDemo1.class, "OverlaidXYPlotDemo1.java"));
//        root.add(this.createNode(OverlaidXYPlotDemo2.class, "OverlaidXYPlotDemo2.java"));
        return root;
    }
    
    private MutableTreeNode createBarChartsNode(final DefaultMutableTreeNode r) {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Bar Charts");
        root.add(this.createNode(SimpleBarChart1.class, "SimpleBarChart1.java"));
        root.add(this.createNode(SimpleBarChart2.class, "SimpleBarChart2.java"));
        root.add(this.createNode(BarLabels.class, "BarLabels.java"));
        root.add(this.createNode(MultiColorBar.class, "MultiColorBar.java"));
        root.add(this.createNode(HistogramWithBellCurve.class, "HistogramWithBellCurve.java"));
//        root.add(this.createNode(BarChartDemo7.class, "BarChartDemo7.java"));
//        root.add(this.createNode(BarChartDemo8.class, "BarChartDemo8.java"));
//        root.add(this.createNode(BarChartDemo9.class, "BarChartDemo9.java"));
//        root.add(this.createNode(BarChartDemo10.class, "BarChartDemo10.java"));
//        root.add(this.createNode(BarChartDemo11.class, "BarChartDemo11.java"));
//        root.add(this.createNode(IntervalBarChartDemo1.class, "IntervalBarChartDemo1.java"));
//        root.add(this.createNode(LayeredBarChartDemo1.class, "LayeredBarChartDemo1.java"));
//        root.add(this.createNode(LayeredBarChartDemo2.class, "LayeredBarChartDemo2.java"));
//        root.add(this.createNode(SlidingCategoryDatasetDemo1.class, "SlidingCategoryDatasetDemo1.java"));
//        root.add(this.createNode(SlidingCategoryDatasetDemo2.class, "SlidingCategoryDatasetDemo2.java"));
//        root.add(this.createNode(StatisticalBarChartDemo1.class, "StatisticalBarChartDemo1.java"));
//        root.add(this.createNode(SurveyResultsDemo1.class, "SurveyResultsDemo1.java"));
//        root.add(this.createNode(SurveyResultsDemo2.class, "SurveyResultsDemo2.java"));
//        root.add(this.createNode(SurveyResultsDemo3.class, "SurveyResultsDemo3.java"));
//        root.add(this.createNode(WaterfallChartDemo1.class, "WaterfallChartDemo1.java"));
        return root;
    }
    
    private MutableTreeNode createLineChartsNode(final DefaultMutableTreeNode r) {
    	final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Line Charts");
        root.add(this.createNode(SimpleLineChart.class, "SimpleLineChart.java"));
        root.add(this.createNode(CompactLineChart.class, "CompactLineChart.java"));
        root.add(this.createNode(MultiLineChart.class, "MultiLineChart.java"));
        root.add(this.createTrendingCurveFittingNode());

//        final MutableTreeNode defaultNode;
//        defaultNode=this.createNode(MultiLineChart.class, "MultiLineChart.java");
//        root.add(defaultNode);
//        root.add(this.createNode(LineChartDemo2.class, "LineChartDemo2.java"));
//        root.add(this.createNode(LineChartDemo3.class, "LineChartDemo3.java"));
//        root.add(this.createNode(LineChartDemo4.class, "LineChartDemo4.java"));
//        root.add(this.createNode(LineChartDemo5.class, "LineChartDemo5.java"));
//        root.add(this.createNode(LineChartDemo6.class, "LineChartDemo6.java"));
//        root.add(this.createNode(LineChartDemo7.class, "LineChartDemo7.java"));
//        root.add(this.createNode(LineChartDemo8.class, "LineChartDemo8.java"));
//        root.add(this.createNode(StatisticalLineChartDemo1.class, "StatisticalLineChartDemo1.java"));
//        root.add(this.createNode(XYSplineRendererDemo1.class, "XYSplineRendererDemo1.java"));
//        root.add(this.createNode(XYStepRendererDemo1.class, "XYStepRendererDemo1.java"));
//        root.add(this.createNode(XYStepRendererDemo2.class, "XYStepRendererDemo2.java"));
//        this.defaultChartPath = new TreePath(new Object[] { r, root, defaultNode });
        return root;
    }

    private MutableTreeNode createAreaChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Area Charts");
        root.add(this.createNode(SimpleAreaChart.class, "SimpleAreaChart.java"));
        root.add(this.createNode(AreaLineChart.class, "AreaLineChart.java"));
        root.add(this.createNode(DualXAxis.class, "DualXAxis.java"));
        return root;
    }

     // 趋势和曲线拟合
    private MutableTreeNode createTrendingCurveFittingNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Trending and Curve Fitting");
        root.add(this.createNode(GeneralCurveFitting.class, "GeneralCurveFitting.java"));
        root.add(this.createNode(TrendLineChart.class, "TrendLineChart.java"));
        return root;
    }

    private MutableTreeNode createFloatingBoxOrWaterfallChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Floating Box/Waterfall Charts");
        root.add(this.createNode(BoxWhiskerChart1.class, "BoxWhiskerChart1.java"));
        root.add(this.createNode(BoxWhiskerChart2.class, "BoxWhiskerChart2.java"));
        return root;
    }
    
    private MutableTreeNode createTimeSeriesChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Time Series Charts");
//        root.add(this.createNode(TimeSeriesDemo1.class, "TimeSeriesDemo1.java"));
//        root.add(this.createNode(TimeSeriesDemo2.class, "TimeSeriesDemo2.java"));
//        root.add(this.createNode(TimeSeriesDemo3.class, "TimeSeriesDemo3.java"));
//        root.add(this.createNode(TimeSeriesDemo4.class, "TimeSeriesDemo4.java"));
//        root.add(this.createNode(TimeSeriesDemo5.class, "TimeSeriesDemo5.java"));
//        root.add(this.createNode(TimeSeriesDemo6.class, "TimeSeriesDemo6.java"));
//        root.add(this.createNode(TimeSeriesDemo7.class, "TimeSeriesDemo7.java"));
//        root.add(this.createNode(TimeSeriesDemo8.class, "TimeSeriesDemo8.java"));
//        root.add(this.createNode(TimeSeriesDemo9.class, "TimeSeriesDemo9.java"));
//        root.add(this.createNode(TimeSeriesDemo10.class, "TimeSeriesDemo10.java"));
//        root.add(this.createNode(TimeSeriesDemo11.class, "TimeSeriesDemo11.java"));
//        root.add(this.createNode(TimeSeriesDemo12.class, "TimeSeriesDemo12.java"));
//        root.add(this.createNode(TimeSeriesDemo13.class, "TimeSeriesDemo13.java"));
//        root.add(this.createNode(TimeSeriesDemo14.class, "TimeSeriesDemo14.java"));
//        root.add(this.createNode(PeriodAxisDemo1.class, "PeriodAxisDemo1.java"));
//        root.add(this.createNode(PeriodAxisDemo2.class, "PeriodAxisDemo2.java"));
//        root.add(this.createNode(PeriodAxisDemo3.class, "PeriodAxisDemo3.java"));
//        root.add(this.createNode(RelativeDateFormatDemo1.class, "RelativeDateFormatDemo1.java"));
//        root.add(this.createNode(DeviationRendererDemo1.class, "DeviationRendererDemo1.java"));
//        root.add(this.createNode(DeviationRendererDemo2.class, "DeviationRendererDemo2.java"));
//        root.add(this.createNode(DifferenceChartDemo1.class, "DifferenceChartDemo1.java"));
//        root.add(this.createNode(DifferenceChartDemo2.class, "DifferenceChartDemo2.java"));
//        root.add(this.createNode(CompareToPreviousYearDemo.class, "CompareToPreviousYearDemo.java"));
        return root;
    }

    private MutableTreeNode createFinancialChartsNode(final DefaultMutableTreeNode r) {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Financial Charts");
        root.add(this.createNode(SimpleHLOCChart.class, "SimpleHLOCChart.java"));
        root.add(this.createNode(SimpleCandlestickChart.class, "SimpleCandlestickChart.java"));
        root.add(this.createNode(FinanceChart1.class, "FinanceChart1.java"));
        root.add(this.createNode(FinanceChart2.class, "FinanceChart2.java"));
//        root.add(this.createNode(FinanceChartCustomSymbols.class, "FinanceChartCustomSymbols.java"));

        final MutableTreeNode defaultNode;
        defaultNode=this.createNode(FinanceChartCustomSymbols.class, "FinanceChartCustomSymbols.java");
        root.add(defaultNode);
        root.add(this.createNode(FinanceDemoChart.class, "FinanceDemoChart.java"));
//        root.add(this.createNode(PriceVolumeDemo2.class, "PriceVolumeDemo2.java"));
//        root.add(this.createNode(YieldCurveDemo1.class, "YieldCurveDemo1.java"));
		this.defaultChartPath = new TreePath(new Object[] { r, root, defaultNode });
        return root;
    }
    
    private MutableTreeNode createSankeyChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Sankey Charts");
//        root.add(this.createNode(FlowPlotDemo1.class, "FlowPlotDemo1.java"));
//        root.add(this.createNode(FlowPlotDemo2.class, "FlowPlotDemo2.java"));
        return root;
    }

    private MutableTreeNode createXYChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("XY Charts");
//        root.add(this.createNode(ScatterPlotDemo1.class, "ScatterPlotDemo1.java"));
//        root.add(this.createNode(ScatterPlotDemo2.class, "ScatterPlotDemo2.java"));
//        root.add(this.createNode(ScatterPlotDemo3.class, "ScatterPlotDemo3.java"));
//        root.add(this.createNode(LogAxisDemo1.class, "LogAxisDemo1.java"));
//        root.add(this.createNode(Function2DDemo1.class, "Function2DDemo1.java"));
//        root.add(this.createNode(XYBlockChartDemo1.class, "XYBlockChartDemo1.java"));
//        root.add(this.createNode(XYBlockChartDemo2.class, "XYBlockChartDemo2.java"));
//        root.add(this.createNode(XYBlockChartDemo3.class, "XYBlockChartDemo3.java"));
//        root.add(this.createNode(XYLineAndShapeRendererDemo1.class, "XYLineAndShapeRendererDemo1.java"));
//        root.add(this.createNode(XYLineAndShapeRendererDemo2.class, "XYLineAndShapeRendererDemo2.java"));
//        root.add(this.createNode(XYSeriesDemo1.class, "XYSeriesDemo1.java"));
//        root.add(this.createNode(XYSeriesDemo2.class, "XYSeriesDemo2.java"));
//        root.add(this.createNode(XYSeriesDemo3.class, "XYSeriesDemo3.java"));
//        root.add(this.createNode(XYShapeRendererDemo1.class, "XYShapeRendererDemo1.java"));
//        root.add(this.createNode(VectorPlotDemo1.class, "VectorPlotDemo1.java"));
        return root;
    }
    
    private MutableTreeNode createMeterChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Meter & Dial Charts");
//        root.add(this.createNode(DialDemo1.class, "DialDemo1.java"));
//        root.add(this.createNode(DialDemo2.class, "DialDemo2.java"));
//        root.add(this.createNode(DialDemo2a.class, "DialDemo2a.java"));
//        root.add(this.createNode(DialDemo3.class, "DialDemo3.java"));
//        root.add(this.createNode(DialDemo4.class, "DialDemo4.java"));
//        root.add(this.createNode(DialDemo5.class, "DialDemo5.java"));
//        root.add(this.createNode(MeterChartDemo1.class, "MeterChartDemo1.java"));
//        root.add(this.createNode(MeterChartDemo2.class, "MeterChartDemo2.java"));
//        root.add(this.createNode(MeterChartDemo3.class, "MeterChartDemo3.java"));
//        root.add(this.createNode(ThermometerDemo1.class, "ThermometerDemo1.java"));
        return root;
    }
    
    private MutableTreeNode createMultipleAxisChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Multiple Axis Charts");
//        root.add(this.createNode(DualAxisDemo1.class, "DualAxisDemo1.java"));
//        root.add(this.createNode(DualAxisDemo2.class, "DualAxisDemo2.java"));
//        root.add(this.createNode(DualAxisDemo3.class, "DualAxisDemo3.java"));
//        root.add(this.createNode(DualAxisDemo4.class, "DualAxisDemo4.java"));
//        root.add(this.createNode(DualAxisDemo5.class, "DualAxisDemo5.java"));
//        root.add(this.createNode(MultipleAxisDemo1.class, "MultipleAxisDemo1.java"));
//        root.add(this.createNode(MultipleAxisDemo2.class, "MultipleAxisDemo2.java"));
//        root.add(this.createNode(MultipleAxisDemo3.class, "MultipleAxisDemo3.java"));
//        root.add(this.createNode(ParetoChartDemo1.class, "ParetoChartDemo1.java"));
        return root;
    }
    
    private MutableTreeNode createCombinedAxisChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Combined Axis Charts");
//        root.add(this.createNode(CombinedCategoryPlotDemo1.class, "CombinedCategoryPlotDemo1.java"));
//        root.add(this.createNode(CombinedCategoryPlotDemo2.class, "CombinedCategoryPlotDemo2.java"));
//        root.add(this.createNode(CombinedTimeSeriesDemo1.class, "CombinedTimeSeriesDemo1.java"));
//        root.add(this.createNode(CombinedXYPlotDemo1.class, "CombinedXYPlotDemo1.java"));
//        root.add(this.createNode(CombinedXYPlotDemo2.class, "CombinedXYPlotDemo2.java"));
//        root.add(this.createNode(CombinedXYPlotDemo3.class, "CombinedXYPlotDemo3.java"));
//        root.add(this.createNode(CombinedXYPlotDemo4.class, "CombinedXYPlotDemo4.java"));
        return root;
    }
    
    private MutableTreeNode createGanttChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Gantt Charts");
//        root.add(this.createNode(GanttDemo1.class, "GanttDemo1.java"));
//        root.add(this.createNode(GanttDemo2.class, "GanttDemo2.java"));
//        root.add(this.createNode(SlidingGanttDatasetDemo1.class, "SlidingGanttDatasetDemo1.java"));
//        root.add(this.createNode(XYTaskDatasetDemo1.class, "XYTaskDatasetDemo1"));
//        root.add(this.createNode(XYTaskDatasetDemo2.class, "XYTaskDatasetDemo2"));
        return root;
    }
    
    private MutableTreeNode createMiscellaneousChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Miscellaneous");
        root.add(this.createAnnotationsNode());
        root.add(this.createCrosshairChartsNode());
        root.add(this.createDynamicChartsNode());
        root.add(this.createItemLabelsNode());
        root.add(this.createLegendNode());
        root.add(this.createMarkersNode());
        root.add(this.createOrientationNode());
//        root.add(this.createNode(AxisOffsetsDemo1.class, "AxisOffsetsDemo1.java"));
//        root.add(this.createNode(BubbleChartDemo1.class, "BubbleChartDemo1.java"));
//        root.add(this.createNode(BubbleChartDemo2.class, "BubbleChartDemo2.java"));
//        root.add(this.createNode(CategoryLabelPositionsDemo1.class, "CategoryLabelPositionsDemo1.java"));
//        root.add(this.createNode(CategoryStepChartDemo1.class, "CategoryStepChartDemo1.java"));
//        root.add(this.createNode(CompassDemo1.class, "CompassDemo1.java"));
//        root.add(this.createNode(CompassFormatDemo1.class, "CompassFormatDemo1.java"));
//        root.add(this.createNode(CompassFormatDemo2.class, "CompassFormatDemo2.java"));
//        root.add(this.createNode(EventFrequencyDemo1.class, "EventFrequencyDemo1.java"));
//        root.add(this.createNode(GradientPaintTransformerDemo1.class, "GradientPaintTransformerDemo1.java"));
//        root.add(this.createNode(GridBandDemo1.class, "GridBandDemo1.java"));
//        root.add(this.createNode(HideSeriesDemo1.class, "HideSeriesDemo1.java"));
//        root.add(this.createNode(HideSeriesDemo2.class, "HideSeriesDemo2.java"));
//        root.add(this.createNode(HideSeriesDemo3.class, "HideSeriesDemo3.java"));
//        root.add(this.createNode(MultipleDatasetDemo1.class, "MultipleDatasetDemo1.java"));
//        root.add(this.createNode(PolarChartDemo1.class, "PolarChartDemo1.java"));
//        root.add(this.createNode(ScatterRendererDemo1.class, "ScatterRendererDemo1.java"));
//        root.add(this.createNode(SpiderWebChartDemo1.class, "SpiderWebChartDemo1.java"));
//        root.add(this.createNode(SymbolAxisDemo1.class, "SymbolAxisDemo1.java"));
//        root.add(this.createNode(ThermometerDemo1.class, "ThermometerDemo1.java"));
//        root.add(this.createNode(ThermometerDemo2.class, "ThermometerDemo2.java"));
//        root.add(this.createNode(ThumbnailDemo1.class, "ThumbnailDemo1.java"));
//        root.add(this.createNode(TranslateDemo1.class, "TranslateDemo1.java"));
//        root.add(this.createNode(WindChartDemo1.class, "WindChartDemo1.java"));
//        root.add(this.createNode(YIntervalChartDemo1.class, "YIntervalChartDemo1.java"));
//        root.add(this.createNode(YIntervalChartDemo2.class, "YIntervalChartDemo2.java"));
        return root;
    }
    
    private MutableTreeNode createAnnotationsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Annotations");
//        root.add(this.createNode(AnnotationDemo1.class, "AnnotationDemo1.java"));
//        root.add(this.createNode(AnnotationDemo2.class, "AnnotationDemo2.java"));
//        root.add(this.createNode(CategoryPointerAnnotationDemo1.class, "CategoryPointerAnnotationDemo1.java"));
//        root.add(this.createNode(XYBoxAnnotationDemo1.class, "XYBoxAnnotationDemo1.java"));
//        root.add(this.createNode(XYPolygonAnnotationDemo1.class, "XYPolygonAnnotationDemo1.java"));
//        root.add(this.createNode(XYTitleAnnotationDemo1.class, "XYTitleAnnotationDemo1.java"));
        return root;
    }
    
    private MutableTreeNode createCrosshairChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Crosshairs");
//        root.add(this.createNode(CrosshairOverlayDemo1.class, "CrosshairOverlayDemo1.java"));
//        root.add(this.createNode(CrosshairOverlayDemo2.class, "CrosshairOverlayDemo2.java"));
//        root.add(this.createNode(CrosshairDemo1.class, "CrosshairDemo1.java"));
//        root.add(this.createNode(CrosshairDemo2.class, "CrosshairDemo2.java"));
//        root.add(this.createNode(CrosshairDemo3.class, "CrosshairDemo3.java"));
//        root.add(this.createNode(CrosshairDemo4.class, "CrosshairDemo4.java"));
        return root;
    }
    
    private MutableTreeNode createDynamicChartsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Dynamic Charts");
//        root.add(this.createNode(DynamicDataDemo1.class, "DynamicDataDemo1.java"));
//        root.add(this.createNode(DynamicDataDemo2.class, "DynamicDataDemo2.java"));
//        root.add(this.createNode(DynamicDataDemo3.class, "DynamicDataDemo3.java"));
//        root.add(this.createNode(MouseOverDemo1.class, "MouseOverDemo1.java"));
        return root;
    }
    
    private MutableTreeNode createItemLabelsNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Item Labels");
//        root.add(this.createNode(ItemLabelDemo1.class, "ItemLabelDemo1.java"));
//        root.add(this.createNode(ItemLabelDemo2.class, "ItemLabelDemo2.java"));
//        root.add(this.createNode(ItemLabelDemo3.class, "ItemLabelDemo3.java"));
//        root.add(this.createNode(ItemLabelDemo4.class, "ItemLabelDemo4.java"));
//        root.add(this.createNode(ItemLabelDemo5.class, "ItemLabelDemo5.java"));
        return root;
    }
    
    private MutableTreeNode createLegendNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Legends");
//        root.add(this.createNode(LegendWrapperDemo1.class, "LegendWrapperDemo1.java"));
        return root;
    }
    
    private MutableTreeNode createMarkersNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Markers");
//        root.add(this.createNode(CategoryMarkerDemo1.class, "CategoryMarkerDemo1.java"));
//        root.add(this.createNode(CategoryMarkerDemo2.class, "CategoryMarkerDemo2.java"));
//        root.add(this.createNode(MarkerDemo1.class, "MarkerDemo1.java"));
//        root.add(this.createNode(MarkerDemo2.class, "MarkerDemo2.java"));
        return root;
    }
    
    private MutableTreeNode createOrientationNode() {
        final DefaultMutableTreeNode root = new DefaultMutableTreeNode("Plot Orientation");
//        root.add(this.createNode(PlotOrientationDemo1.class, "PlotOrientationDemo1.java"));
//        root.add(this.createNode(PlotOrientationDemo2.class, "PlotOrientationDemo2.java"));
        return root;
    }
    
    private void displayDescription(final String fileName) {
        final URL descriptionURL = ChartDirectorDemo.class.getResource(fileName);
        if (descriptionURL != null) {
            try {
                this.descriptionPane.setPage(descriptionURL);
            }
            catch (IOException e) {
                System.err.println("Attempted to read a bad URL: " + descriptionURL);
            }
        }
        else {
            System.err.println("Couldn't find file: " + fileName);
        }
    }
    
    @Override
    public void valueChanged(final TreeSelectionEvent event) {
        final TreePath path = event.getPath();
        final Object obj = path.getLastPathComponent();
        if (obj != null) {
            final DefaultMutableTreeNode n = (DefaultMutableTreeNode)obj;
            final Object userObj = n.getUserObject();
            if (userObj instanceof DemoDescription) {
                final DemoDescription dd = (DemoDescription)userObj;

                // Async invoke.
				new Thread(() -> {
					SwingUtilities.invokeLater(new DisplayDemo(this, dd));
				}).start();
            }
            else {
                this.chartContainer.removeAll();
                this.chartContainer.add(this.createNoDemoSelectedPanel());
                this.displayPanel.validate();
                this.displayDescription("select.html");
            }
        }
    }
    
    private JPanel createNoDemoSelectedPanel() {
        final JPanel panel = new JPanel(new FlowLayout()) {
			private static final long serialVersionUID = 1L;

			@Override
            public String getToolTipText() {
                return "(" + this.getWidth() + ", " + this.getHeight() + ")";
            }
        };
        ToolTipManager.sharedInstance().registerComponent(panel);
        panel.add(new JLabel("No demo selected"));
        panel.setPreferredSize(DEFAULT_CONTENT_SIZE);
        return panel;
    }
    
    public static void main(final String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                }
                catch (Exception e3) {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    }
                    catch (Exception e2) {
                        e2.printStackTrace();
                    }
                }
                final ChartDirectorDemo demo = new ChartDirectorDemo("ChartDirector 7.0 Demo Collection");
                demo.pack();
                UIUtils.centerFrameOnScreen(demo);
                demo.setVisible(true);
            }
        });
    }


    static class DisplayDemo implements Runnable
    {
        private ChartDirectorDemo app;
        private DemoDescription demoDescription;
        
        public DisplayDemo(final ChartDirectorDemo app, final DemoDescription d) {
            this.app = app;
            this.demoDescription = d;
        }

        @Override
        public void run() {
            try {
                final Class<?> c = this.demoDescription.getDemoClass();
                if (FinanceDemoChart.class.equals(c)) {
                	FinanceDemoChart dialog = (FinanceDemoChart) c.getConstructor(JFrame.class).newInstance(app);
                	dialog.setVisible(true);
				}else {
                final Method m = c.getDeclaredMethod("createDemoPanel", JPanel.class);
                m.invoke(null, this.app.chartContainer);
                String fileName="EmptyDescription";
//                final String className = fileName = c.getName();
//                final int i = className.lastIndexOf(46);
//                if (i > 0) {
//                    fileName = className.substring(i + 1);
//                }
                fileName += ".html";
                this.app.displayDescription(fileName);
				}
            }
            catch (Exception e) {
				e.printStackTrace();
			}
        }
    }

    static class DemoDescription {

    	private Class<?> demoClass;
        private String description;
        
        public DemoDescription(final Class<?> demoClass, final String demoDescription) {
            this.demoClass = demoClass;
            this.description = demoDescription;
        }
        
        public Class<?> getDemoClass() {
            return this.demoClass;
        }
        
        public String getDescription() {
            return this.description;
        }
        
        @Override
        public String toString() {
            return this.description;
        }
        
    }

}
